{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "9c794bc7",
   "metadata": {},
   "source": [
    "# 构建检索问答链"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f3d0f2c3-3bd9-4de1-bbd2-e0e2b09161c8",
   "metadata": {},
   "source": [
    "我们已经介绍了如何根据自己的本地知识文档，搭建一个向量知识库。 在接下来的内容里，我们将使用搭建好的向量数据库，对 query 查询问题进行召回，并将召回结果和 query 结合起来构建 prompt，输入到大模型中进行问答。   "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95d8d968-8d98-47b9-8885-dc17d24dce76",
   "metadata": {},
   "source": [
    "## 1. 加载向量数据库\n",
    "\n",
    "首先，我们加载在前一章已经构建的向量数据库。注意，此处你需要使用和构建时相同的 Emedding。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "adc86262-da78-4fda-a597-600d54057062",
   "metadata": {},
   "source": [
    "### Milvus"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d8349782-7ca4-4ebb-acc1-6097ff5cee99",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.vectorstores import Milvus\n",
    "from langchain_community.embeddings import OllamaEmbeddings\n",
    "my_emb = OllamaEmbeddings(base_url='http://129.201.70.35:11434', model=\"dengcao/Qwen3-Embedding-0.6B:F16\")\n",
    "\n",
    "# Milvus 连接参数\n",
    "vectordb = Milvus(\n",
    "        embedding_function=my_emb,\n",
    "        collection_name=\"ZXVMAXS\",  # Milvus 集合名称\n",
    "        connection_args={\n",
    "            \"host\": \"129.201.70.35\",  # Milvus 服务器地址\n",
    "            \"port\": \"19530\",  # Milvus 默认端口\n",
    "        },\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "14c39416-a9b2-4de1-9fb6-5c521a7fd2f4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'pk': 461017040453077208, 'producer': 'Apache FOP Version 2.6', 'creator': 'DITA Open Toolkit', 'creationdate': '2023-05-23T21:45:33+08:00', 'source': '../data_base/knowledge_path/VMAX-S/ZXVMAX-S（V6.23）产品描述（上网日志业务）.pdf', 'file_path': '../data_base/knowledge_path/VMAX-S/ZXVMAX-S（V6.23）产品描述（上网日志业务）.pdf', 'total_pages': 29, 'format': 'PDF 1.4', 'title': '目录', 'author': '', 'subject': '', 'keywords': '', 'moddate': '', 'trapped': '', 'modDate': '', 'creationDate': \"D:20230523214533+08'00'\", 'page': 13}, page_content='4\\xa0功能本章包含如下主题：\\uf06c上网日志保存\\n10\\n\\uf06c上网日志查询\\n10\\n\\uf06c上网日志批量导入查询\\n11\\n\\uf06c日志管理\\n11\\n\\uf06c账号管理\\n11\\n\\uf06c角色管理\\n12\\n\\uf06c资源监控\\n12\\n\\uf06c告警管理\\n12\\n\\uf06c省级网关对接\\n12\\n\\uf06c拨测结果自动比对功能\\n12\\n\\uf06cNAT日志入库功能\\n13\\n\\uf06c北向接口\\n13\\n\\uf06c上网日志历史查询\\n13\\n\\uf06c云化上网日志XDR查询\\n13\\n以下介绍ZXVMAX-S的主要的功能。\\n4.1\\xa0上网日志保存\\uf06c支持使用Gbase数据库或HDFS保存上网日志。\\uf06c上网日志保存时间可配置，最短保存7天时间，最长可保存一年时间。\\uf06c支持自动清理超过保存时间的上网日志。\\n4.2\\xa0上网日志查询可通过web界面指定查询条件，查询用户上网日志。支持的查询条件：\\uf06c时间范围+公网IP\\n\\uf06c时间范围+目的IP\\n\\uf06c时间范围+MSISDN\\n\\uf06c时间范围+IMSI\\n\\uf06c时间范围+URL\\n\\uf06c支持组合以上五种基础条件，或在基础条件上增加指定公网端口、目的端口，做更精确的查询。\\n10\\nSJ-20220623151803-017|2023-03-30（R1.0）'),\n",
       " Document(metadata={'pk': 461017040453076907, 'producer': 'Apache FOP Version 2.3', 'creator': 'DITA Open Toolkit', 'creationdate': '2022-06-23T16:34:22+08:00', 'source': '../data_base/knowledge_path/VMAX-S/ZXVMAX-S（V6.20.80.02）告警处理.pdf', 'file_path': '../data_base/knowledge_path/VMAX-S/ZXVMAX-S（V6.20.80.02）告警处理.pdf', 'total_pages': 330, 'format': 'PDF 1.4', 'title': '目录', 'author': '', 'subject': '', 'keywords': '', 'moddate': '', 'trapped': '', 'modDate': '', 'creationDate': \"D:20220623163422+08'00'\", 'page': 297}, page_content='ZXVMAX-S多维价值分析系统告警处理可能原因确保实际填充率达到预期填充率处理步骤确保实际填充率达到预期填充率\\n7.2194000200303HTTP接口下行TCP重传报文数完整率(小时)告警描述确保实际填充率达到预期填充率告警级别警告可能原因确保实际填充率达到预期填充率处理步骤确保实际填充率达到预期填充率\\n7.2204000200304HTTP接口TCP建链响应时延（ms）完整率(小时)告警描述确保实际填充率达到预期填充率告警级别警告可能原因确保实际填充率达到预期填充率处理步骤确保实际填充率达到预期填充率\\n7.2214000200305HTTP接口TCP建链确认时延（ms）完整率(小时)告警描述确保实际填充率达到预期填充率\\n276\\nSJ-20220623151803-011|2022-06-20（R1.0）')]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "results = vectordb.similarity_search(query=\"什么是vmax的上网日志系统？\", k=2)\n",
    "results"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f7f8dbd-ecd5-449d-9753-aedc2b74289c",
   "metadata": {},
   "source": [
    "## 2. 创建一个 LLM"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "026bd74f-3dd0-496e-905b-950a444bb7a7",
   "metadata": {},
   "source": [
    "在这里，我们调用 OpenAI 的 API 创建一个 LLM，当然你也可以使用其他 LLM 的 API 进行创建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "a89fb297-888a-4d35-b519-90eba639893c",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_34805/2506360335.py:3: LangChainDeprecationWarning: The class `Ollama` was deprecated in LangChain 0.3.1 and will be removed in 1.0.0. An updated version of the class exists in the :class:`~langchain-ollama package and should be used instead. To use it run `pip install -U :class:`~langchain-ollama` and import as `from :class:`~langchain_ollama import OllamaLLM``.\n",
      "  my_llm = Ollama(base_url='http://129.201.70.35:11434', model='qwen3:8B', temperature=0.1)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'<think>\\n嗯，用户发来“你好”，我需要回应。首先，要友好，用中文。然后，可能用户想开始对话，所以应该主动询问他们有什么需要帮助的。保持自然，不要太机械。比如可以说“你好！有什么我可以帮你的吗？”或者更亲切一点，比如“你好呀！今天过得怎么样？有什么我可以协助你的吗？”这样既友好又开放，鼓励用户进一步交流。同时要注意语气，避免过于正式，让对话更轻松。另外，可能用户只是测试，所以需要保持灵活，根据后续回复调整。总之，回应要简洁、友好，引导用户说出具体需求。\\n</think>\\n\\n你好呀！今天过得怎么样？有什么我可以协助你的吗？😊'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_community.llms import Ollama\n",
    "\n",
    "my_llm = Ollama(base_url='http://129.201.70.35:11434', model='qwen3:8B', temperature=0.1)\n",
    "\n",
    "my_llm.invoke(\"你好\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "73e85917-7a21-4de3-b45a-19d00152382a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# from langchain_community.llms import VLLMOpenAI  # 注意类名为 VLLMOpenAI[3](@ref)\n",
    "# my_llm = VLLMOpenAI(\n",
    "#     openai_api_key=\"token-abc123\",          # vLLM 无需鉴权，设为空字符串[3](@ref)\n",
    "#     openai_api_base=\"http://129.201.70.35:9991/v1\",  # 服务端地址\n",
    "#     model_name=\"my_qwen3_8b\",  # 需与部署的模型路径一致\n",
    "#     # max_tokens=1024,                # 控制生成文本最大长度\n",
    "#     temperature=0.6,               # 生成多样性参数\n",
    "#     streaming=True                  # 支持流式输出（可选）\n",
    "# )\n",
    "# response = my_llm.invoke(\"你是谁？/no_think\")\n",
    "# response"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f361e27-cafb-48bf-bb41-50c9cb3a4f7e",
   "metadata": {},
   "source": [
    "## 3. 构建检索问答链"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "248b5e3c-1bc9-40e9-83c7-0594c2e7727d",
   "metadata": {},
   "source": [
    "prompts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "91be03f4-264d-45cb-bebd-223c1c5747fd",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "template = \"\"\"你是VMAX运维助手，使用以下上下文来回答问题。如果你不知道答案，就说你不知道，不要试图编造答案。总是在回答的最后说“谢谢你的提问！”。\n",
    "{context}\n",
    "问题: {question}\n",
    "\"\"\"\n",
    "\n",
    "QA_CHAIN_PROMPT = PromptTemplate(input_variables=[\"context\",\"question\", \"sources\"],\n",
    "                                 template=template)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2d06d7f-1dca-4d10-b5cd-3a23e9d91200",
   "metadata": {},
   "source": [
    "#### 创建一个基于模板的检索链： 基础检索版本"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8b05eb57-edf5-4b35-9538-42c2b8f5cc16",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chains import RetrievalQA\n",
    "\n",
    "# 基础检索\n",
    "base_retriever = vectordb.as_retriever(search_kwargs={\"k\": 10})\n",
    "base_retriever = vectordb.as_retriever(\n",
    "    search_kwargs={\"k\": 15},  # 扩大召回池\n",
    "    search_type=\"mmr\",  # 最大边际相关性算法（网页5）\n",
    "    # metadata_filter={\"source\": \"../data_base/knowledge_path/VMAX-S/ZXVMAX-S（V6.23）产品描述（5GC业务）.pdf\"}  # 元数据过滤\n",
    ")\n",
    "\n",
    "qa_chain = RetrievalQA.from_chain_type(my_llm,\n",
    "                                       retriever=base_retriever,\n",
    "                                       return_source_documents=True,\n",
    "                                       chain_type_kwargs={\"prompt\":QA_CHAIN_PROMPT})\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "503a7972-a673-41ca-a028-647169d19fcb",
   "metadata": {},
   "source": [
    "## 4.检索问答链效果测试"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "acc2223f-6fb5-4504-bfcd-ac74ca9ff2fa",
   "metadata": {},
   "source": [
    "### 4.1 基于召回结果和 query 结合起来构建的 prompt 效果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fa1a61eb-feea-4fff-8063-a20c3b392aed",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_34805/3541758222.py:2: LangChainDeprecationWarning: The method `Chain.__call__` was deprecated in langchain 0.1.0 and will be removed in 1.0. Use :meth:`~invoke` instead.\n",
      "  result = qa_chain({\"query\": question_1})\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "大模型+知识库后回答 question_1 的结果：\n",
      "<think>\n",
      "\n",
      "</think>\n",
      "\n",
      "ZXVMAX-S的5GC业务是指ZXVMAX-S多维价值分析系统在5G核心网（5G Core Network, 5GC）场景中的应用。该系统面向用户的网络运维和运营分析，能够从网元、用户、终端、业务等多个维度，对业务使用过程中的质量和特征进行全方位的挖掘。它支持实时分析（如网络质量、数据业务质量等）和事后分析（如用户投诉、问题分析等），为移动通信网络的运维和运营提供全面支撑。在5GC业务中，ZXVMAX-S系统能够帮助运营商优化网络性能、提升服务质量，并为市场发展提供数据支撑。谢谢你的提问！\n"
     ]
    }
   ],
   "source": [
    "question_1 = \"什么是ZXVMAX-S的5GC业务？/no_think\"\n",
    "result = qa_chain({\"query\": question_1})\n",
    "print(\"大模型+知识库后回答 question_1 的结果：\")\n",
    "print(result[\"result\"])\n",
    "# print(result[\"source_documents\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "2707095e-21d0-4e2b-8a5b-0c02258d2ce0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "大模型+知识库后回答 question_2 的结果：\n",
      "<think>\n",
      "\n",
      "</think>\n",
      "\n",
      "我是一个VMAX运维助手，专注于提供与VMAX系统相关的技术支持和信息。关于周杰伦的问题，我无法提供相关信息。谢谢你的提问！\n"
     ]
    }
   ],
   "source": [
    "question_2 = \"周杰伦是谁？/no_think\"\n",
    "result = qa_chain({\"query\": question_2})\n",
    "print(\"大模型+知识库后回答 question_2 的结果：\")\n",
    "print(result[\"result\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4195cfa-1fc8-41a9-8984-91f2e5fbe013",
   "metadata": {},
   "source": [
    "### 4.2 无知识库大模型自己回答的效果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "569fbe28-2e2d-4042-b3a1-65326842bdc9",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_34805/46941173.py:5: LangChainDeprecationWarning: The method `BaseLLM.predict` was deprecated in langchain-core 0.1.7 and will be removed in 1.0. Use :meth:`~invoke` instead.\n",
      "  my_llm.predict(prompt_template)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'<think>\\n\\n</think>\\n\\nZXVMAX-S 是华为推出的一款面向5G网络的虚拟化核心网（5GC）解决方案，其全称是 **ZXVMAX-S 5G Core**。它是一种基于云原生架构的5G核心网业务平台，支持多种5GC业务功能，如：\\n\\n- **UE（用户设备）管理（AMF）**\\n- **会话管理（SMF）**\\n- **接入和移动性管理（AMF）**\\n- **策略控制（PCF）**\\n- **网络切片管理（NSSF）**\\n- **统一数据管理（UDM）**\\n- **服务化接口（NRF）**\\n- **策略控制（PCF）**\\n- **网络暴露功能（NEF）**\\n\\n### ZXVMAX-S 的5GC业务特点：\\n\\n1. **云原生架构**：基于微服务架构，支持灵活扩展和高可用性。\\n2. **多业务支持**：支持多种5G业务场景，如eMBB（增强移动宽带）、URLLC（超可靠低时延通信）、mMTC（大规模机器通信）等。\\n3. **开放接口**：支持与第三方应用、网络切片管理平台、业务链管理平台等进行对接。\\n4. **灵活部署**：支持云化部署（如NFVI）、虚拟化部署（如VNF）和混合部署。\\n5. **高可靠性**：支持多实例冗余、故障自动切换、负载均衡等机制，保障业务连续性。\\n6. **支持网络切片**：支持不同业务场景下的网络切片管理，满足不同行业对网络性能、安全、隔离等的不同需求。\\n\\n### 应用场景：\\n\\n- **工业互联网**：支持高可靠、低时延的工业自动化控制。\\n- **车联网（V2X）**：支持超低时延和高可靠性的车联网通信。\\n- **智慧城市**：支持大规模设备接入和数据处理。\\n- **远程医疗**：支持高带宽、低时延的远程手术和诊断。\\n- **AR/VR**：支持高带宽、低时延的沉浸式体验。\\n\\n### 总结：\\n\\nZXVMAX-S 的5GC业务是华为面向5G时代推出的核心网解决方案，支持多种5G业务功能和场景，具备高可靠性、灵活性和开放性，适用于多种行业和应用场景，是构建5G网络的重要基础设施。'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prompt_template = \"\"\"请回答下列问题:\n",
    "                            {}\"\"\".format(question_1)\n",
    "\n",
    "### 基于大模型的问答\n",
    "my_llm.predict(prompt_template)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "d0d3a813-db19-4be5-8926-ad8298e3e2b1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'<think>\\n\\n</think>\\n\\n周杰伦（Jay Chou），1970年1月18日出生于中国台湾省新北市，是中国台湾的著名音乐人、歌手、音乐制作人、导演和演员。他是华语乐坛最具影响力的音乐人之一，以其独特的音乐风格、创新的编曲方式和深情的歌词而闻名。\\n\\n周杰伦的音乐融合了多种元素，包括流行、R&B、嘻哈、中国风、古典音乐等，他的作品常常带有浓厚的东方文化色彩。他不仅在音乐创作上表现出色，还涉足电影导演领域，执导了多部电影，如《不能说的秘密》《天台上的魔幻时刻》等，均获得广泛好评。\\n\\n周杰伦的代表作品包括《七里香》《青花瓷》《菊花台》《告白气球》《听妈妈的话》等，这些歌曲不仅在华语地区广为传唱，也在全球范围内拥有大量粉丝。他多次获得金曲奖等多项音乐大奖，是华语乐坛的标志性人物之一。\\n\\n总的来说，周杰伦不仅是一位才华横溢的音乐人，也是华语流行文化的重要代表人物。'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prompt_template = \"\"\"请回答下列问题:\n",
    "                            {}\"\"\".format(question_2)\n",
    "\n",
    "### 基于大模型的问答\n",
    "my_llm.predict(prompt_template)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51b9ba4a-053d-409a-a632-63336c2bdf84",
   "metadata": {},
   "source": [
    "> ⭐ 通过以上两个问题，我们发现 LLM 对于一些近几年的知识以及非常识性的专业问题，回答的并不是很好。而加上我们的本地知识，就可以帮助 LLM 做出更好的回答。另外，也有助于缓解大模型的“幻觉”问题。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce0fee88-5d13-43dd-9415-180d9e6bf2e7",
   "metadata": {},
   "source": [
    "## 5. 添加历史对话的记忆功能"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69e633b4-879d-4e67-8f3e-d5c82f1712c3",
   "metadata": {},
   "source": [
    "现在我们已经实现了通过上传本地知识文档，然后将他们保存到向量知识库，通过将查询问题与向量知识库的召回结果进行结合输入到 LLM 中，我们就得到了一个相比于直接让 LLM 回答要好得多的结果。在与语言模型交互时，你可能已经注意到一个关键问题 - **它们并不记得你之前的交流内容**。这在我们构建一些应用程序（如聊天机器人）的时候，带来了很大的挑战，使得对话似乎缺乏真正的连续性。这个问题该如何解决呢？\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e41cc4ec-5b42-4c8c-aafc-65745c9e59b2",
   "metadata": {},
   "source": [
    "### 5.1 记忆（Memory）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc053f6c-aeed-42b9-938a-2c52020f1327",
   "metadata": {},
   "source": [
    "在本节中我们将介绍 LangChain 中的储存模块，即如何将先前的对话嵌入到语言模型中的，使其具有连续对话的能力。我们将使用 `ConversationBufferMemory` ，它保存聊天消息历史记录的列表，这些历史记录将在回答问题时与问题一起传递给聊天机器人，从而将它们添加到上下文中。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "e2ed5b18-1bd6-4160-b68e-4300ccc5d4b3",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_1270322/2228008247.py:3: LangChainDeprecationWarning: Please see the migration guide at: https://python.langchain.com/docs/versions/migrating_memory/\n",
      "  memory = ConversationBufferMemory(\n"
     ]
    }
   ],
   "source": [
    "from langchain.memory import ConversationBufferMemory\n",
    "\n",
    "memory = ConversationBufferMemory(\n",
    "    memory_key=\"chat_history\",  # 与 prompt 的输入变量保持一致。\n",
    "    return_messages=True  # 将以消息列表的形式返回聊天记录，而不是单个字符串\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b1d2c797-5706-438c-ae11-bf4aa81795ba",
   "metadata": {},
   "source": [
    "关于更多的 Memory 的使用，包括保留指定对话轮数、保存指定 token 数量、保存历史对话的总结摘要等内容，请参考 langchain 的 Memory 部分的相关文档。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b56fe278-2109-4b7b-9604-2ea030b18caa",
   "metadata": {},
   "source": [
    "### 5.2 对话检索链（ConversationalRetrievalChain）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76abe746-8e01-4067-9675-354deecdfde7",
   "metadata": {},
   "source": [
    "对话检索链（ConversationalRetrievalChain）在检索 QA 链的基础上，增加了处理对话历史的能力。\n",
    "\n",
    "它的工作流程是:\n",
    "1. 将之前的对话与新问题合并生成一个完整的查询语句。\n",
    "2. 在向量数据库中搜索该查询的相关文档。\n",
    "3. 获取结果后,存储所有答案到对话记忆区。\n",
    "4. 用户可在 UI 中查看完整的对话流程。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd98d830-0f2f-4794-acc2-4c23428bdd8c",
   "metadata": {},
   "source": [
    "这种链式方式将新问题放在之前对话的语境中进行检索，可以处理依赖历史信息的查询。并保留所有信\n",
    "息在对话记忆中，方便追踪。\n",
    "\n",
    "接下来让我们可以测试这个对话检索链的效果："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "a4ba5ed5-24c4-4725-be2f-5d24bfbdee89",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import PromptTemplate\n",
    "from langchain.chains import ConversationalRetrievalChain\n",
    "# 修改后的Prompt模板（添加chat_history变量）\n",
    "template = \"\"\"你是VMAX运维助手，请参考以下对话历史和上下文来回答问题：\n",
    "    {chat_history}\n",
    "    \n",
    "    相关上下文：\n",
    "    {context}\n",
    "    \n",
    "    问题：{question}\n",
    "    回答结束时说“谢谢你的提问！”\n",
    "    \"\"\"\n",
    "    \n",
    "QA_PROMPT = PromptTemplate(\n",
    "        input_variables=[\"chat_history\", \"context\", \"question\"],\n",
    "        template=template\n",
    "    )\n",
    "    \n",
    "# 创建对话链\n",
    "qa_chain = ConversationalRetrievalChain.from_llm(\n",
    "        llm=my_llm,\n",
    "        retriever=vectordb.as_retriever(),\n",
    "        memory=memory,\n",
    "        combine_docs_chain_kwargs={\"prompt\": QA_PROMPT},\n",
    "        chain_type=\"stuff\"\n",
    "    )\n",
    "    \n",
    "    # result = qa_chain({\"question\": question})\n",
    "    # return result[\"answer\"]\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c97f98ff-9b0b-40f7-a3b4-7481fb6597d0",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "93c837e3-afae-4e0c-8b59-9e9fbc3e2a98",
   "metadata": {},
   "source": [
    "然后基于答案进行下一个问题“为什么这门课需要教这方面的知识？”："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "2e96fbc6-935e-40ac-81b5-3a220fe05741",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "回答：<think>\n",
      "好的，用户问的是“什么是ZXVMAX-S的5GC业务？”，我需要根据提供的上下文来回答。首先，我得仔细看看相关上下文里有没有提到ZXVMAX-S的5GC业务相关内容。\n",
      "\n",
      "在上下文中，有提到“ZXVMAX-S多维价值分析系统产品描述（5GC业务）图5-8会话跟踪组网逻辑图”，这说明ZXVMAX-S的5GC业务可能与产品描述和组网逻辑有关。另外，其他部分主要涉及告警处理、接口完整率和合规率的问题，可能和5GC业务的具体功能或应用场景相关。\n",
      "\n",
      "不过，上下文中的信息比较零散，没有直接定义5GC业务是什么。可能需要结合已知的5GC知识来补充。5GC（5G Core）是5G网络的核心部分，负责控制面和用户面功能，支持网络切片、边缘计算等特性。ZXVMAX-S作为多维价值分析系统，可能在5GC业务中用于数据收集、分析，帮助运营商优化网络性能和业务策略。\n",
      "\n",
      "但根据用户提供的上下文，重点可能在于ZXVMAX-S系统如何支持5GC业务，比如通过会话跟踪、接口监控等。因此，回答应结合产品描述和组网逻辑，说明ZXVMAX-S在5GC中的角色，如数据分析、性能监控等，同时提到相关告警处理机制确保服务质量和合规性。\n",
      "\n",
      "需要注意的是，用户提供的上下文可能没有详细说明5GC业务的具体定义，所以回答需要基于现有信息，并适当扩展，但避免超出上下文范围。最后，确保回答结束时有“谢谢你的提问！”。\n",
      "</think>\n",
      "\n",
      "ZXVMAX-S的5GC业务是指基于5G核心网（5G Core）的多维价值分析系统，主要用于支持5G网络中的业务数据分析、性能监控及优化。该系统通过采集和分析5GC（5G Core Cloud）相关接口（如S11、SGS等）的数据，帮助运营商实现对网络切片、会话管理、服务指标等关键业务的精细化运营，从而提升网络效率和用户体验。其核心功能包括告警处理、填充率监控（如接口完整率、合规率）以及组网逻辑分析（如会话跟踪），确保5GC业务的稳定运行和资源优化。  \n",
      "\n",
      "谢谢你的提问！\n",
      "\n",
      "==================================================\n",
      "\n",
      "回答：<think>\n",
      "好的，用户现在问的是ZXVMAX-S的5GC业务包含哪些具体功能。我需要根据之前的对话历史和上下文来回答。首先，回顾之前的对话，用户已经询问过ZXVMAX-S的5GC业务是什么，而我的回答提到了多维价值分析系统，涉及5GC的组网逻辑、告警处理、接口完整率和合规率监控等。\n",
      "\n",
      "现在用户进一步询问具体功能，我需要详细列出这些功能。根据上下文中的信息，ZXVMAX-S的5GC业务功能包括：\n",
      "\n",
      "1. **会话分析**：针对PDU会话创建、修改、释放的失败流程进行分析，通过多接口关联分析定位首次失败点，并进行失败码聚类分析，辅助问题定位。同时支持在小区、网元、终端等维度进行TOP分析。\n",
      "\n",
      "2. **切换分析**：针对5GC内切换流程的失败码进行分析，关联多接口信息，分析切换成功率及各阶段时延，提升用户5G驻留比。\n",
      "\n",
      "3. **4/5G互操作分析**：分析4/5G互操作的三种场景（切换、重选、重接入），关联控制面信息，评估互操作成功率及时延，优化用户切换体验。\n",
      "\n",
      "4. **告警处理**：监控S11、SGS等接口的完整率和合规率（如MMEPort、MSCServerPort、APN等），当实际填充率未达预期时触发告警，帮助定位问题根源。\n",
      "\n",
      "5. **组网逻辑分析**：通过会话跟踪组网逻辑图（如图5-8）分析网络结构，支持对5GC业务的精细化运营和资源优化。\n",
      "\n",
      "这些功能共同支持运营商对5GC网络的高效管理，确保服务质量和资源利用率。最后，确保回答结束时有“谢谢你的提问！”。\n",
      "</think>\n",
      "\n",
      "ZXVMAX-S的5GC业务主要包含以下具体功能：  \n",
      "1. **会话流程分析**：针对PDU会话创建、修改、释放的失败流程，通过多接口关联分析定位首次失败点，并对失败码组合进行聚类分析，辅助问题定界；支持按小区、网元、终端等维度进行TOP分析。  \n",
      "2. **切换流程分析**：分析5GC内切换流程的失败码，关联多接口信息，评估切换成功率及各阶段时延，提升用户5G驻留比。  \n",
      "3. **4/5G互操作分析**：针对切换、重选、重接入等场景，关联控制面信息，分析互操作成功率及时延，优化用户切换体验。  \n",
      "4. **告警监控与处理**：实时监控S11、SGS等接口的完整率和合规率（如MMEPort、MSCServerPort、APN等），当实际填充率未达预期时触发告警，辅助问题定位。  \n",
      "5. **组网逻辑分析**：基于会话跟踪组网逻辑图（如图5-8），分析5GC业务的网络结构，支持精细化运营和资源优化。  \n",
      "\n",
      "这些功能共同保障5GC业务的稳定性、性能及服务质量。  \n",
      "谢谢你的提问！\n",
      "\n",
      "==================================================\n",
      "\n",
      "回答：<think>\n",
      "好的，用户现在希望将之前提到的ZXVMAX-S的5GC业务功能整理成表格。我需要先回顾之前的对话，确保准确理解用户的需求。用户之前询问了ZXVMAX-S的5GC业务包含哪些功能，我详细列出了五个功能点，包括会话流程分析、切换流程分析、4/5G互操作分析、告警监控与处理以及组网逻辑分析。\n",
      "\n",
      "现在用户要求将这些信息整理成表格，我需要将每个功能点转化为表格中的行，可能包括功能名称、描述和应用场景等列。首先，我需要确认用户是否希望表格包含所有提到的功能，或者是否有其他需要补充的信息。根据之前的回答，每个功能点都有具体的描述，因此表格应包含这些细节。\n",
      "\n",
      "另外，用户可能希望表格结构清晰，便于阅读和理解。因此，我需要确定表格的列标题，例如“功能名称”、“功能描述”和“应用场景”等。同时，要确保每个功能点的信息准确无误，与之前的回答一致。例如，会话流程分析需要说明其针对的流程和分析方法，切换流程分析要提到失败码和时延评估，互操作分析要涵盖三种场景等。\n",
      "\n",
      "还需要注意用户可能的深层需求，比如是否需要进一步的技术细节或实际应用案例，但根据当前问题，用户只是要求整理成表格，因此应保持简洁。最后，确保表格格式正确，使用清晰的分隔符，如竖线或连字符，并在结尾加上“谢谢你的提问！”以符合之前的回答风格。\n",
      "</think>\n",
      "\n",
      "| **功能名称**         | **功能描述**                                                                 | **应用场景**                                                                 |\n",
      "|----------------------|------------------------------------------------------------------------------|------------------------------------------------------------------------------|\n",
      "| **会话流程分析**     | 分析PDU会话创建、修改、释放的失败流程，定位首次失败点，失败码聚类分析，支持按小区/网元/终端维度TOP分析 | 优化5G会话管理成功率，提升用户体验                                         |\n",
      "| **切换流程分析**     | 分析5GC内切换流程的失败码，关联多接口信息，评估切换成功率及各阶段时延         | 提升用户5G驻留比，优化网络切换性能                                         |\n",
      "| **4/5G互操作分析**   | 分析切换、重选、重接入等场景，关联控制面信息，评估互操作成功率及时延         | 优化4/5G互操作体验，减少用户切换中断                                       |\n",
      "| **告警监控与处理**   | 监控S11、SGS等接口的完整率和合规率（如MMEPort、MSCServerPort、APN等），触发告警 | 快速定位接口填充率异常，保障5GC业务稳定性                                   |\n",
      "| **组网逻辑分析**     | 基于会话跟踪组网逻辑图（如图5-8），分析5GC业务网络结构                       | 支持网络资源优化和精细化运营，提升5GC组网效率                               |\n",
      "\n",
      "谢谢你的提问！\n",
      "\n",
      "==================================================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "questions = [\n",
    "    \"什么是ZXVMAX-S的5GC业务？\",\n",
    "    \"包含哪些功能\", \n",
    "    \"整理成表格\"  \n",
    "]\n",
    "\n",
    "for question in questions:\n",
    "    result = qa_chain({\"question\": question})  # Pass string directly, not dict\n",
    "    # print(f\"问题：{question}\")\n",
    "    print(f\"回答：{result['answer']}\")\n",
    "    # print(\"对话历史：\", memory.load_memory_variables({}))\n",
    "    print(\"\\n\" + \"=\"*50 + \"\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b62782f0-a996-4461-af2e-3fa4ce304c59",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (env_rag)",
   "language": "python",
   "name": "env_rag"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
